package br.usjt.mazerobot.commons.navegacao;

import java.io.Serializable;

public class Mapa implements Serializable {

    /*
     * Indicador de versao da classe, classes serializadas em arquivos 
     * só serão deserializados se as versoes forem compativeis
     */
    private static final long serialVersionUID = 1L;
    
    private byte[][] mapa = new byte[11][11];
    private short controleLinha = (short) (mapa.length / 2); //Variável para controlar o centro X do mapa
    private short controleColuna = (short) (mapa[0].length / 2); //Variável para controlar o centro Y do mapa

    public void adiciona(Celula celula) {

        short linhaAtual = (short) (celula.getX() + controleLinha);
        short colunaAtual = (short) (celula.getY() + controleColuna);

        mapa[linhaAtual][colunaAtual] = celula.getStatus();
        verificaCapacidade(linhaAtual, colunaAtual);

    }

    public byte consulta(Celula celula) {
        short linhaAtual = (short) (celula.getX() + controleLinha);
        short colunaAtual = (short) (celula.getY() + controleColuna);
        return mapa[linhaAtual][colunaAtual];
    }

    private void verificaCapacidade(short linha, short coluna) {

        int linhas = mapa.length;
        int colunas = mapa[0].length;

        byte[][] mapaTemporario;


        if (linha <= 0) { //Caso o mapa aumente para a esquerda

            int linhasAtual = (linhas * 3) / 2 + 1;
            mapaTemporario = new byte[linhasAtual][colunas];


            for (int i = 0; i < linhas; i++) {
                for (int j = 0; j < colunas; j++) {
                    mapaTemporario[i + linhasAtual - linhas][j] = mapa[i][j];
                }
            }

            controleLinha += (linhasAtual - linhas);
            mapa = mapaTemporario;
            linhas = mapa.length; //Atualiza a quantidade de colunas para caso seja ampliada linhas e colunas

        }

        if (linha >= (linhas - 1)) { //Caso o mapa aumente para direita

            int linhasAtual = (linhas * 3) / 2 + 1;
            mapaTemporario = new byte[linhasAtual][colunas];

            for (int i = 0; i < linhas; i++) {
                for (int j = 0; j < colunas; j++) {
                    mapaTemporario[i][j] = mapa[i][j];
                }
            }

            mapa = mapaTemporario;
            linhas = mapa.length;
        }

        if (coluna <= 0) { //Caso o mapa aumente para cima

            int colunasAtual = (colunas * 3) / 2 + 1;
            mapaTemporario = new byte[linhas][colunasAtual];


            for (int i = 0; i < linhas; i++) {
                for (int j = 0; j < colunas; j++) {

                    mapaTemporario[i][j + colunasAtual - colunas] = mapa[i][j];
                }
            }
            controleColuna += (colunasAtual - colunas);
            mapa = mapaTemporario;
            colunas = mapa[0].length;



        }
        if (coluna >= (colunas - 1)) { //Caso o mapa aumente para baixo

            int colunasAtual = (colunas * 3) / 2 + 1;
            mapaTemporario = new byte[linhas][colunasAtual];

            for (int i = 0; i < linhas; i++) {
                for (int j = 0; j < colunas; j++) {
                    mapaTemporario[i][j] = mapa[i][j];
                }
            }

            //Não precisa atualizar porque é o último if.
            mapa = mapaTemporario;
        }
    }

    
    /**
     * Busca os pontos no mapa que o Status é diferente de vazio
     * @return os pontos extremos do mapa
     * indice 0 - menor x
     * indice 1 - maior x
     * indice 2 - menor y
     * indice 3 - maior y
     */
    public short[] getAreaUtilMapa() {
        short menorX = 0 , maiorX = 0, menorY = 0, maiorY = 0;

        for(int x = 0; x < mapa.length; x++){
            for(int y = 0; y < mapa[0].length; y++){
                if(mapa[x][y] > 0){
                    if(menorX > (x-controleLinha)){
                        menorX = (short)(x-controleLinha);
                    }
                    if(menorY > (y-controleColuna)){
                        menorY = (short)(y-controleColuna);
                    }
                    if(maiorX < (x-controleLinha)){
                        maiorX = (short)(x-controleLinha);
                    }
                    if(maiorY < (y-controleColuna)){
                        maiorY = (short)(y-controleColuna);
                    }
                }
            }
        }
        return new short[]{menorX,maiorX,menorY,maiorY};
    }
}
